package arg

import (
	"errors"
	"fmt"
	"github.com/gurkankaymak/hocon"
	"db2s/global"
	"reflect"
	"strconv"
	"strings"
)

//https://github.com/ustc-zzzz/HOCON-CN-Translation/blob/master/HOCON.md#%E5%AE%9A%E4%B9%89
//https://zhuanlan.zhihu.com/p/631662028

//// trimdanyin 去除字符串首尾"
//var trimdanyin = func(s, sb string) (s1 string) {
//	if strings.HasPrefix(s, sb) && strings.HasSuffix(s, sb) {
//		s1 = s[1 : len(s)-1]
//	}
//	return s1
//}

// 接口返回
func (rc *ConfigParameter) anyToJsonString(key string, s any) (f string) {
	switch reflect.TypeOf(s).String() {
	case "string":
		f = fmt.Sprintf("\"%s\":\"%v\"", key, s)
	case "time.Duration":
		f = fmt.Sprintf("\"%s\":\"%v\"", key, s)
	case "[]string":
		f = fmt.Sprintf("\"%s\":[\"%v\"]", key, strings.Join(s.([]string), "\",\""))
	case "bool":
		f = fmt.Sprintf("\"%s\":%v", key, s)
	case "map[string]string":
		var s1 []string
		for k, v := range s.(map[string]string) {
			s1 = append(s1, fmt.Sprintf("\"%s\":\"%s\"", k, v))
		}
		if len(s1) > 0 {
			f = fmt.Sprintf("\"%s\":{%s}", key, strings.Join(s1, ","))
		} else {
			f = fmt.Sprintf("\"%s\":{}", key)
		}
	case "map[string][]string", "map[string]interface {}":
		var s1 []string
		switch reflect.TypeOf(s).String() {
		case "map[string][]string":
			for k, v := range s.(map[string][]string) {
				s1 = append(s1, rc.anyToJsonString(k, v))
			}
		case "map[string]interface {}":
			for k, v := range s.(map[string]any) {
				s1 = append(s1, rc.anyToJsonString(k, v))
			}
		}
		if len(s1) > 0 {
			f = fmt.Sprintf("\"%s\":{%s}", key, strings.Join(s1, ","))
		} else {
			f = fmt.Sprintf("\"%s\":{}", key)
		}
	case "map[string]map[string]string":
		var s1 []string
		for k, v := range s.(map[string]map[string]string) {
			s1 = append(s1, rc.anyToJsonString(k, v))
		}
		f = fmt.Sprintf("\"%s\":{%s}", key, strings.Join(s1, ","))
	case "map[string]map[string][]string":
	case "map[string]map[string]map[string]string":
		var s1 []string
		for k, v := range s.(map[string]map[string]map[string]string) {
			s1 = append(s1, rc.anyToJsonString(k, v))
		}
	case "int":
		f = fmt.Sprintf("\"%s\":%v", key, s)
	case "[]int":
		var s1 []string
		for _, v := range s.([]int) {
			s1 = append(s1, strconv.Itoa(v))
		}
		f = fmt.Sprintf("\"%s\":[%s]", key, strings.Join(s1, ","))
	}
	return
}

// 获取hoconMap的key值
func (rc *ConfigParameter) hoconfMapKey(f1 *hocon.Config, s string) (lol map[string]int) {
	lol = make(map[string]int)
	for k := range f1.GetObject(s) {
		lol[k]++
	}
	return
}

// 判断子选项参数的值是否为空，存在则返回false，不存在则返回true
func (rc *ConfigParameter) mustExistParameterValue(f3 *hocon.Config, s string) bool {
	if strings.EqualFold(f3.GetObject(s).String(), "{}") {
		return true
	} else if strings.EqualFold(f3.GetObject(s).String(), "") {
		return true
	}
	return false
}

// 获取参数对象是否存在,true表示存在，false表示不存在
var boolJudge = func(f1 *hocon.Config, s string) (b bool) {
	defer func() {
		if err := recover(); err != nil {
			b = false //不存在
		} else {
			if s == "" || f1.GetObject(s) == nil {
				b = false
			} else {
				b = true //存在
			}
		}
	}()
	f1.GetObject(s)
	return b
}

// 针对hoconConfig中的value值进行判断
func (rc *ConfigParameter) getHoconConfigVal(ff *hocon.Config, f1, s1 string) (s any) {
	if strings.EqualFold(ff.String(), "{}") {
		return nil
	}
	defer func() {
		if err := recover(); err != nil {
			s = nil
		}
	}()
	if ff.Get(f1) == nil {
		return nil
	}
	switch s1 {
	case "string", "1", "hocon.String":
		r := ff.Get(f1).String()
		if r == "" {
			return nil
		} else {
			return strings.ReplaceAll(r, "\"", "")
		}
	case "int", "3":
		return ff.GetInt(f1)
	case "map", "map[string]interface {}", "map[string]string":
		return ff.GetStringMapString(f1)
	case "[]string", "slice", "2":
		var res []string
		for _, v := range ff.GetStringSlice(f1) {
			if v == "" {
				return nil
			} else {
				res = append(res, strings.ReplaceAll(v, "\"", ""))
			}
		}
		return res
	case "[]int":
		return ff.GetIntSlice(f1)
	case "map[string][]string":
		var s4 = make(map[string][]string)
		for k := range ff.GetStringMap(f1) {
			s4[k] = rc.getHoconConfigVal(ff.GetConfig(f1), k, "[]string").([]string)
		}
		return s4
	case "mapAny":
		var s3 = make(map[string]any)
		for k, v := range ff.GetStringMap(f1) {
			s3[k] = rc.getHoconConfigVal(ff.GetConfig(f1), k, fmt.Sprintf("%v", v.Type()))
		}
		return s3
	case "hocon.Array":
		//fmt.Println("----", ff, s)
	case "bool", "4":
		return ff.GetBoolean(f1)
	case "time.Duration":
		return ff.GetDuration(f1)
	case "map[string]map[string]string":
		var s4 = make(map[string]map[string]string)
		for k := range ff.GetStringMap(f1) {
			s4[k] = rc.getHoconConfigVal(ff.GetConfig(f1), k, "map[string]string").(map[string]string)
		}
		return s4
	case "map[string]map[string]map[string]string":
		var s4 = make(map[string]map[string]map[string]string)
		for k := range ff.GetStringMap(f1) {
			s4[k] = rc.getHoconConfigVal(ff.GetConfig(f1), k, "map[string]map[string]string").(map[string]map[string]string)
		}
		return s4
	case "hocon.Object", "0":
		var s4 = make(map[string]any)
		for k, v := range ff.GetStringMap(f1) {
			s4[k] = rc.getHoconConfigVal(ff.GetConfig(f1), f1, reflect.TypeOf(v).String())
		}
	case "[]map[string]interface {}":
		//fmt.Println(ff.GetStringSlice(f1))
	}
	return nil
}

// 针对hoconfig中的value值进行判断
func (rc *ConfigParameter) getHoconConfigVal1(ff *hocon.Config, f1, s1 string) (s any) {
	if strings.EqualFold(ff.String(), "{}") {
		return nil
	}
	defer func() {
		if err := recover(); err != nil {
			s = nil
		}
	}()
	if ff.Get(f1) == nil {
		return nil
	}

	switch s1 {
	case "string", "hocon.String":
		if ff.Get(f1).String() == "" {
			return nil
		} else {
			return ff.GetString(f1)
		}
	case "int", "hocon.Int":
		return int64(ff.GetInt(f1))
	case "[]string":
		return ff.GetStringSlice(f1)
	case "bool", "hocon.Boolean":
		return ff.GetBoolean(f1)
	case "time.Duration":
		return ff.GetDuration(f1)
	case "map[string]interface {}", "map[string][]string":
		var ss = make(map[string]any)
		for k, v := range ff.GetStringMap(f1) {
			ss[k] = rc.getHoconConfigVal1(ff.GetConfig(f1), k, fmt.Sprintf("%v", reflect.TypeOf(v)))
		}
		return ss
	case "hocon.Object":
		var ss = make(map[string]any)
		for k, v := range ff.GetStringMap(f1) {
			ss[k] = rc.getHoconConfigVal1(ff.GetConfig(f1), k, fmt.Sprintf("%v", reflect.TypeOf(v)))
		}
		return ss
	case "hocon.Array":
		var ss []string
		for _, v := range ff.GetStringSlice(f1) {
			ss = append(ss, v)
		}
		return ss
	}
	return nil
}

func getFirstLevelName(hConfFin *hocon.Config) (FirstL firstLevel, err error) {
	var (
		LevelName = make(map[string]any)
	)
	for _, k := range global.StructNameJsonToSlice(getFirstLevel()) {
		k1 := fmt.Sprintf("%v", k)
		LevelName[k1] = hConfFin.GetObject(k1)
	}
	if err = global.MapToStructJson(LevelName, &FirstL); err != nil {
		return
	}
	return
}
func (rc *ConfigParameter) getObjectName(checkMod string) string {
	var objectName string
	if boolJudge(rc.FirstL1.Rules.ToConfig(), checkMod) {
		objectName = checkMod
	} else {
		objectName = "rows"
	}
	return objectName
}

// 判断子选项参数是否存在，不存在则返回false，存在则返回true
func (rc *ConfigParameter) mustExistParameter(f3 *hocon.Config, s string, m map[string]any) bool {
	var m1 = make(map[string]any)
	for k, v := range m {
		m1[k] = v
	}
	for k := range f3.GetObject(s) {
		if _, ok := m1[k]; ok {
			delete(m1, k)
		}
	}
	if len(m1) > 0 {
		return false
	}
	return true
}

type modeCheckSwitch struct {
	logS    bool
	DSnsS   bool
	RulesS  bool
	DBPoolS bool
	RepairS bool
	ResultS bool
	SchemaS bool
}

func getCheckSet(mode string) modeCheckSwitch {
	switch mode {
	case "task":
		return modeCheckSwitch{
			logS:    true,
			DSnsS:   true,
			RulesS:  true,
			ResultS: true,
		}
	case "sync", "struct", "object", "rows":
		return modeCheckSwitch{
			logS:    true,
			DSnsS:   true,
			RulesS:  true,
			DBPoolS: true,
			RepairS: true,
			ResultS: true,
			SchemaS: true,
		}
	default:
		return modeCheckSwitch{}
	}
}

// LevelParameterCheck1 一级、二级参数标签合法性校验
func LevelParameterCheck1(hConfFin *hocon.Config) (s SecondaryLevel, err error) {
	var (
		FirstL firstLevel
	)
	if FirstL, err = getFirstLevelName(hConfFin); err != nil {
		return
	}
	if s.RulesV, err = rulesSecondaryLevelParameter(FirstL.Rules); err != nil {
		return
	}
	q := getCheckSet(s.RulesV.CheckMode)
	if q.DSnsS {
		if s.DSnsV, err = dSNsSecondaryLevelParameter(FirstL.DSNs); err != nil {
			return
		}
	}
	if q.logS {
		if err = logInit(FirstL.Logs.ToConfig()); err != nil {
			return SecondaryLevel{}, err
		}
	}
	if q.DBPoolS {
		if s.DBPoolV, err = dbPoolSecondaryLevelParameter(FirstL.DBPool); err != nil {
			return
		}
	}
	if q.RepairS {
		if s.RepairV, err = repairSecondaryLevelParameter(FirstL.Repair); err != nil {
			return
		}
	}
	if q.ResultS {
		if s.ResultV, err = resultOutSecondaryLevelParameter(s.RulesV.CheckMode, FirstL.Result); err != nil {
			return
		}
	}
	if q.SchemaS {
		if s.TableObject, err = schemaSecondaryLevelParameter(FirstL.Schema.ToConfig()); err != nil {
			return
		}
	}
	//if err := rc.inspectionLevelParameter(); err != nil {
	//	return
	//}
	s.FunctionalMode = s.RulesV.CheckMode
	return
}

/*
该函数用于读取配置文件中的配置参数
*/
func getConfig1(Config string) (s SecondaryLevel, err error) {
	var (
		hConfFin *hocon.Config
	)
	//处理配置文件中的特殊字符
	if hConfFin, err = hocon.ParseResource(Config); err != nil {
		// 处理解析错误
		var parseErr *hocon.ParseError
		if errors.As(err, &parseErr) {
			fmt.Printf("Error parsing configuration file:\n")
			fmt.Printf("Message: %s\n", parseErr.Error())
			err = errors.New(fmt.Sprintf("error while parsing configuration: %v", err))
		}
		return
	}
	if s, err = LevelParameterCheck1(hConfFin); err != nil {
		return
	}
	return
}
